package com.cskaoyan.service.wx.coupon;

import com.cskaoyan.dao.polularize.MarketCouponDao;
import com.cskaoyan.dao.usercoupon.UserCouponDao;
import com.cskaoyan.dao.wx.cart.WXCartMapper;
import com.cskaoyan.model.BaseData;
import com.cskaoyan.model.admin.coupon.bo.CouponListBo;
import com.cskaoyan.model.admin.pojo.MarketCouponPojo;
import com.cskaoyan.model.admin.user.userbeans.UserListVo;
import com.cskaoyan.model.realm.WxLoginUserData;
import com.cskaoyan.model.wx.cart.Cart;
import com.cskaoyan.model.wx.user.UserCouponPojo;
import com.cskaoyan.model.wx.wxcoupon.WxCouponDto;
import com.cskaoyan.model.wx.wxcoupon.bo.CouponBaseBo;
import com.cskaoyan.model.wx.wxcoupon.vo.CouponBaseVo;
import com.cskaoyan.model.wx.wxcoupon.vo.CouponMyListVo;
import com.cskaoyan.model.wx.wxcoupon.vo.CouponSelectVo;
import com.cskaoyan.model.wx.wxcoupon.vo.WxCouponVo;

import com.cskaoyan.service.admin.popularize.CouPonService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import org.apache.shiro.SecurityUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

@Service
public class WXCouponServiceImpl implements WXCouponService {

    @Autowired
    MarketCouponDao coupon;

    @Autowired
    UserCouponDao userCouponDao;

    @Autowired
    CouPonService service;

    @Autowired
    WXCartMapper cartMapper;

    /***
     *
     *  这里需要查询的是通用券，并且状态为0【正常】， 没有被删除[deleted=0]
     */
    @Override
    public BaseData getCouponListInfo(Integer limit, Integer page) {

        // 设置查询条件
        CouponListBo couponListBo = new CouponListBo();
        couponListBo.setStatus(0);
        couponListBo.setType(0);


        PageHelper.startPage(page, limit);
        List<MarketCouponPojo> list = coupon.getMarketCouponInfo(couponListBo);
        PageInfo<MarketCouponPojo> info = new PageInfo<>(list);

        // 参数转换
        return transferCouponPojo(list, info, limit, page);
    }

    /**
     * 这里的查询和上面的一致，首页展示前5项即可
     *
     * @return
     */
    @Override
    public List<WxCouponVo> getHomeCouponList() {

        return getCouponListInfo(5, 1).getList();
    }

    /**
     * @param couponId : 优惠券ID，验证逻辑如下：
     *                 todo:更新的时候只更新特定的
     *                 1. 更新数据库状态，更新最新时间，和状态保证可用状态，
     *                 2. 检查数量，检查所用的优惠券是否是可用状态。
     *                 3. 检查限额是否满足
     *                 4. 同时更新coupon表和用户的user_coupon表
     */
    @Override
    public boolean receiveCoupon(int couponId) {
        WxLoginUserData principal = (WxLoginUserData) SecurityUtils.getSubject().getPrincipal();

        // 更新数据库状态，更新一下最新时间，也即是绝对时间下的status的值
        // 保证时间和状态合法
        service.checkAndUpdateCouponInfo(couponId);

        MarketCouponPojo pojo = coupon.getMarketCouponInfoById(couponId);

        // 数量不够,状态有问题，或者优惠券被删除
        if (pojo.getTotal() == 0 || pojo.getStatus() != 0 || pojo.getDeleted() == 1) {
            return false;
        }

        // 拿到用户所拥有的，如果有限额，并且用户用于的超过了限额，返回false
        int userTotal = userCouponDao.getSpecialCouponAccount(principal.getId(), couponId);
        if (pojo.getLimit() != 0 && userTotal >= pojo.getLimit()) {
            return false;
        }
        // 更新优惠券的数据,如果数量为零，下架,如果为-1代表不限量
        int count = pojo.getTotal();
        int status = pojo.getStatus();
        if (count != -1 && --count == 0) {
            status = 2;
        }
        coupon.updateMarketCouponTotal(couponId, count, status);


        UserCouponPojo userCoupon = initUserCouponPojo(principal.getId(), couponId, pojo);

        int result = userCouponDao.receiveNewCoupon(userCoupon);
        if (result == 1) {
            return true;
        }
        return false;
    }

    /**
     * @param info :分页信息 :page/limit 以及优惠券状态信息status
     */
    @Override
    public CouponBaseVo getCouponMyList(CouponBaseBo info) {


        WxLoginUserData principal = (WxLoginUserData) SecurityUtils.getSubject().getPrincipal();

        PageHelper.startPage(info.getPage(), info.getLimit());
        List<WxCouponVo> list = userCouponDao.getUserCouponByStatus(principal.getId(), info.getStatus());
        PageInfo<WxCouponVo> pageResult = new PageInfo<>(list);

        CouponBaseVo couponBaseVo = new CouponBaseVo();
        couponBaseVo.setLimit(info.getLimit());
        couponBaseVo.setPage(info.getPage());
        couponBaseVo.setPages(pageResult.getPages());
        couponBaseVo.setTotal((int) pageResult.getTotal());

        couponBaseVo.setList(list);

        return couponBaseVo;
    }

    /**
     * 1. 拿到兑换码对应的数据库对象
     * 2. 验证coupon数据和状态的正确性
     * 3. 验证数量[取出的时候进行了以上的验证，但是没有验证时间以及用户限制]
     * 4. 更新两个数据库
     */
    @Override
    public boolean exchangeCoupon(String code, Integer userId) {
        MarketCouponPojo pojo = coupon.getMarketCouponInfoByCode(code);
        if (pojo.getTimeType() == 1) {
            if (pojo.getEndTime().compareTo(new Date()) <= 0) {
                return false;
            }
        }
        int couponId = pojo.getId();
        int userTotal = userCouponDao.getSpecialCouponAccount(userId, couponId);
        if (pojo.getLimit() != 0 && userTotal >= pojo.getLimit()) {
            return false;
        }
        // 更新优惠券的数据,如果数量为零，下架
        int count = pojo.getTotal();
        int status = pojo.getStatus();
        if (count != -1 && --count == 0) {
            status = 2;
        }
        coupon.updateMarketCouponTotal(couponId, count, status);


        UserCouponPojo userCoupon = initUserCouponPojo(userId, pojo.getId(), pojo);
        int result = userCouponDao.receiveNewCoupon(userCoupon);
        if (result == 1) {
            return true;
        }

        return false;
    }

    /**
     * carID购物车ID，
     */
    @Override
    public BaseData getCouponSelectList(Integer cartId, Integer grouponRulesId) {

        BaseData result = new BaseData();
        result.setPage(1);
        result.setPage(1);

        WxLoginUserData principal = (WxLoginUserData) SecurityUtils.getSubject().getPrincipal();
        Integer userId = principal.getId();
        // 通过购物车ID拿到对应的价钱

        List<Cart> list;
        BigDecimal total = new BigDecimal("0");
        if (cartId == 0) {
            list = cartMapper.selectAllCartInfo(null, cartId);
            total = list.get(0).getPrice().multiply(new BigDecimal(list.get(0).getNumber()));
        } else {
            list = cartMapper.selectAllCartInfo(userId, cartId);
            for (Cart cart : list) {
                total = total.add(cart.getPrice()).multiply(new BigDecimal(cart.getNumber()));
            }
        }

        // 更新user_coupon的状态
        userCouponDao.checkAndUpdateUserCoupon(userId);
        //  拿到可用的dto，判断是否满足使用条件
        List<WxCouponDto> couponDto = userCouponDao.getWxCouponDto(userId);
        for (WxCouponDto item : couponDto) {
            if (item.getGoodsType() == 0) {
                if (item.getMin() < total.doubleValue()) {
                    item.setAvailable(true);
                } else {
                    item.setAvailable(false);
                }
            }
            if (item.getGoodsType() == 1) {
                List<String> goodsValue = Arrays.asList(item.getGoodsValue());
                total = new BigDecimal(0);
                for (Cart cart : list) {
                    if (goodsValue.contains(String.valueOf(cart.getGoodsId()))) {
                        total = total.add(cart.getPrice());
                    }
                }
                if (total.doubleValue() > item.getMin()) {
                    item.setAvailable(true);
                } else {
                    item.setAvailable(false);
                }
            }
            if (item.getGoodsType() == 2) {
                List<String> goodsValue = coupon.getGoodsIdValues(item.getGoodsValue());

                total = new BigDecimal(0);
                for (Cart cart : list) {
                    if (goodsValue.contains(String.valueOf(cart.getGoodsId()))) {
                        total = total.add(cart.getPrice());
                    }
                }
                if (total.doubleValue() > item.getMin()) {
                    item.setAvailable(true);
                } else {
                    item.setAvailable(false);
                }
            }
        }
        List<CouponMyListVo> resultVo = new ArrayList<>();
        for (WxCouponDto item : couponDto) {
            if (item.getAvailable()) {
                resultVo.add(new CouponMyListVo(item));
            }
        }
        result.setList(resultVo);
        result.setTotal(couponDto.size());
        result.setPages(couponDto.size());
        // 返回满足的优惠券
        return result;
    }

    private UserCouponPojo initUserCouponPojo(Integer userId, Integer couponId, MarketCouponPojo coupon) {
        UserCouponPojo pojo = new UserCouponPojo();
        pojo.setUserId(userId);
        pojo.setCouponId(couponId);
        pojo.setStatus(0);

        // 优惠券的时间类型为0就是days固定
        String now = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").format(LocalDateTime.now());
        if (coupon.getTimeType() == 0) {
            pojo.setStartTime(now);
            pojo.setEndTime(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").
                    format(LocalDateTime.now().plusDays(coupon.getDays())));
        } else {
            SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
            pojo.setStartTime(formater.format(coupon.getStartTime()));
            pojo.setEndTime(formater.format(coupon.getEndTime()));
        }

        pojo.setAddTime(now);
        pojo.setUpdateTime(now);
        pojo.setDeleted(false);
        return pojo;
    }


    /***
     *
     * @param list :pojo
     * @param info :info 分页信息，有null判断，可以为null
     * @param limit ：页的数量
     * @param page ：页码
     * @return :返回将Pojo转换成前台需要的vo
     */
    private BaseData transferCouponPojo(List<MarketCouponPojo> list, PageInfo<MarketCouponPojo> info,
                                        Integer limit, Integer page) {

        BaseData response = new BaseData();
        response.setLimit(limit);
        response.setPage(page);
        if (info != null) {
            response.setPages(info.getPages());
            response.setTotal((int) info.getTotal());
        }

        // 将pojo转换成对应的vo
        // 注意，days显式的是时限，如果相对时间就是天数，如果是
        // 绝对时间，那么days就是最后的有效期到期时间
        List<WxCouponVo> result = new ArrayList<>();
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat();
        simpleDateFormat.applyPattern("yyyy-MM-dd HH:mm:ss");

        for (MarketCouponPojo item : list) {
            WxCouponVo couponVo = new WxCouponVo();
            couponVo.setId(item.getId());
            couponVo.setName(item.getName());
            couponVo.setDesc(item.getDesc());
            couponVo.setTag(item.getTag());
            couponVo.setDiscount(item.getDiscount().doubleValue());
            couponVo.setMin(item.getMin().doubleValue());
            if (item.getTimeType() == 0) {
                int i = item.getDays();
                couponVo.setDays(i);
            } else {
                couponVo.setDays(0);
                couponVo.setStartTime(simpleDateFormat.format(item.getStartTime()));
                couponVo.setEndTime(simpleDateFormat.format(item.getEndTime()));
            }
            result.add(couponVo);
        }

        response.setList(result);
        return response;
    }
}
